Skip to content

fix(notifications): retain Notification reference so click handler fires#2238

Merged
richardsolomou merged 2 commits into
mainfrom
posthog-code/fix-notification-focus
May 20, 2026
Merged

fix(notifications): retain Notification reference so click handler fires#2238
richardsolomou merged 2 commits into
mainfrom
posthog-code/fix-notification-focus

Conversation

@richardsolomou
Copy link
Copy Markdown
Member

@richardsolomou richardsolomou commented May 20, 2026

Problem

After #2210, PostHog Code can fire notifications for a different task while you're already focused on another task in the app. Clicking those notifications was supposed to switch you to the task the notification was about (via TaskLinkServicedeepLink.onOpenTaskuseTaskDeepLinknavigateToTask), but the in-app view never changed. On macOS this surfaced as "the app comes to the foreground but stays on the wrong task" — because macOS raises the app on notification click as default OS behaviour, independent of whether the JS click handler runs.

Root cause: ElectronNotifier.notify() (apps/code/src/main/platform-adapters/electron-notifier.ts) created new Notification(...) in a local variable and let it fall out of scope right after .show(). With no retained reference, V8 was free to garbage-collect the JS wrapper before the user clicked, taking the click listener with it. The OS-level notification still rendered fine, but onClick (where taskLinkService.emit(TaskLinkEvent.OpenTask, ...) lives) never fired.

Changes

Hold a reference to each shown Notification in an instance Set<Notification> on ElectronNotifier, and release it when the notification's click or close event fires. This keeps the JS wrapper alive long enough for its events to actually reach JS, with no behavioural change beyond that.

How did you test this?

  • pnpm --filter code typecheck — clean
  • pnpm lint — clean
  • Traced the click path end-to-end: electron-notifier.ts (now retains ref) → notification/service.ts:38-49 (onClick emits OpenTask) → deep-link.ts:27 (subscription yields) → useTaskDeepLink.ts:113-123 (calls handleOpenTask) → navigationStore.navigateToTask (which uses isSameView task-id comparison, so it correctly switches between distinct task-detail views).
  • Tested manually with desktop app and it works.

Publish to changelog?

no


Created with PostHog Code

Clicking a desktop notification was supposed to switch the app to the
task it was about (via TaskLinkService → deepLink.onOpenTask →
useTaskDeepLink → navigateToTask), but the JS click listener was never
firing. On macOS the OS still raised the app on click, so it looked
like "focus works but navigation doesn't" — which is exactly how this
surfaced after PR #2210 started firing notifications for other tasks
while the app was already focused.

Root cause: ElectronNotifier.notify() created `new Notification(...)`
in a local variable and let it fall out of scope after `.show()`. V8
could GC the JS wrapper (and the `click` listener with it) before the
user clicked.

Fix: hold a reference in an instance Set until the notification is
clicked or closed, then release it. No behaviour change beyond keeping
the wrapper alive long enough for its events to reach JS.

Generated-By: PostHog Code
Task-Id: ed71008c-f6e9-4cb8-ad76-006037bcce5b
@richardsolomou richardsolomou force-pushed the posthog-code/fix-notification-focus branch from 60450be to c7ce04f Compare May 20, 2026 04:04
@richardsolomou richardsolomou changed the title fix: focus app when notification is clicked fix(notifications): retain Notification reference so click handler fires May 20, 2026
@richardsolomou richardsolomou requested a review from a team May 20, 2026 04:06
@richardsolomou richardsolomou marked this pull request as ready for review May 20, 2026 04:06
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 20, 2026

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/code/src/main/platform-adapters/electron-notifier.ts:31-34
**Orphaned reference if `close` never fires**

The `active` Set is only cleaned up on `click` or `close`. On some platforms (notably Windows), a notification that expires via OS timeout may not fire the `close` event — leaving the `Notification` object retained in the Set indefinitely. The same applies if Electron emits the `failed` event (display failure): the notification was already added at line 31 but neither `click` nor `close` will follow. In practice this is low-risk (notifications are rare, objects are small), but it's worth also hooking `once("failed", release)` to cover that path.

Reviews (1): Last reviewed commit: "fix(notifications): retain Notification ..." | Re-trigger Greptile

Comment thread apps/code/src/main/platform-adapters/electron-notifier.ts
Cover the path where Electron emits `failed` (display failure) instead
of `close` / `click`, so the active Set doesn't accumulate references
to notifications that were never successfully shown. Same applies to
platforms (notably Windows) where OS-timeout dismissal doesn't fire
`close` — `failed` is the closest signal we have for that.

Generated-By: PostHog Code
Task-Id: ed71008c-f6e9-4cb8-ad76-006037bcce5b
@richardsolomou richardsolomou added the Create Release This will trigger a new release label May 20, 2026
@richardsolomou richardsolomou enabled auto-merge (squash) May 20, 2026 04:19
@richardsolomou richardsolomou merged commit 7f15bec into main May 20, 2026
15 checks passed
@richardsolomou richardsolomou deleted the posthog-code/fix-notification-focus branch May 20, 2026 05:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Create Release This will trigger a new release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants